package com.google.code.p.restrpc.http;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpUriRequest;

/**
 * @author dz
 */
public class DefaultHttpClientAgent implements HttpClientAgent {
    
    private static final Log logger = LogFactory.getLog(DefaultHttpClientAgent.class);
    
    private HttpClient httpClient;
    
    private HttpUriRequest httpUriRequest;
    
    private HttpClientRequest httpClientRequest;
    
    public DefaultHttpClientAgent(HttpClient httpClient,
                                  HttpUriRequest httpUriRequest) {
        super();
        this.httpClient = httpClient;
        this.httpUriRequest = httpUriRequest;
        this.httpClientRequest = new DefaultHttpClientRequest(httpUriRequest.getURI());
    }
    
    public DefaultHttpClientAgent() {
    }
    
    public HttpClient getHttpClient() {
        return httpClient;
    }
    
    public HttpUriRequest getHttpUriRequest() {
        return httpUriRequest;
    }
    
    public HttpClientRequest getHttpClientRequest() {
        return httpClientRequest;
    }
    
    public HttpClientResponse execute() throws IOException {
        try {
            HttpHeaders headers = httpClientRequest.getHeaders();
            
            for (Map.Entry<String, List<String>> entry : headers.headers.entrySet()) {
                String headerName = entry.getKey();
                if (!org.apache.http.HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(headerName) && !org.apache.http.HttpHeaders.TRANSFER_ENCODING.equalsIgnoreCase(headerName)) {
                    for (String headerValue : entry.getValue()) {
                        if (StringUtils.isNotEmpty(headerValue)) {
                            this.httpUriRequest.addHeader(headerName,
                                                          headerValue);
                        }
                    }
                }
            }
            
            // TODO make this configurable and move to a interceptor
            // reduce the CLOSE_WAIT connection,from HTTP 1.1,KEEP_ALIVED always
            // turn-on,need to close it by manual.
            // httpUriRequest.addHeader("Connection", "close");
            
            if (httpUriRequest instanceof HttpEntityEnclosingRequestBase) {
                if (null != httpClientRequest.getBody()) {
                    ((HttpEntityEnclosingRequestBase) httpUriRequest).setEntity((HttpEntity) httpClientRequest.getBody());
                }
            }
            
            HttpResponse response = httpClient.execute(httpUriRequest);
            // if(response.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
            // {
            // throw new HttpClientException("Failed");
            // }
            return new HttpResponseWrapper(response);
        }
        catch (ClientProtocolException e) {
            logger.error(e, e);
            throw new HttpException(e);
        }
    }
    
}
